﻿/*
 * Created by SharpDevelop.
 * User: Corrado Mio
 * Date: 21/06/2012
 * Time: 14:48
 * 
 * La classe mette a disposizione alcuni metodi statici per la
 * creazione di EndPoint in base al tipo di parametri passati.
 * 
 * Esistono due tipi di EndPoint:
 * 
 *      EndPoint
 *          IPEndPoint      l'host e' indicato mediante un indirizzo IVv4 o IVv6
 *          DnsEndPoint     l'host e' indicato mediante un nome, che deve essere
 *                          risolto da un Dns (locale, come "hosts", o quello del
 *                          router casalingo, oppure remoto, come quello del 
 *                          provider ADSL)
 */
using System;
using System.Net;

namespace CSharpExt.Net
{
    /// <summary>
    /// Crea un EndPoint in base al tipo di parametri utilizzati
    /// </summary>
    public static class EndPoints
    {
        public static IPAddress ParseAddress(String host)
        {
            IPAddress address;
            if (IPAddress.TryParse(host, out address))
                return address;
            
            IPAddress[] addresses = Dns.GetHostAddresses(host);
            if (addresses.Length == 0)
                return IPAddress.Parse(host);
            else
                return addresses[0];
        }
        
        /// <summary>
        /// Supporta la sintassi:
        /// 
        ///     host:port
        ///     protocol://user:pwd@host:port/...
        /// 
        /// </summary>
        /// <param name="ipport"></param>
        /// <returns></returns>
        public static EndPoint Parse(String ipport)
        {
            ipport = IpPortOf(ipport);
            
            int pos = ipport.LastIndexOf(':');
            
            return Create(ipport.Substring(0, pos), int.Parse(ipport.Substring(pos+1)));
        }
        
        /// <summary>
        /// Supporta la sintassi:
        /// 
        ///     host:port
        ///     protocol://user:pwd@host:port/...
        /// 
        /// </summary>
        /// <param name="ipport"></param>
        /// <returns></returns>
        public static IPEndPoint ParseIP(String ipport)
        {
            ipport = IpPortOf(ipport);
            
            int pos = ipport.LastIndexOf(':');
            
            return ParseIP(ipport.Substring(0, pos), int.Parse(ipport.Substring(pos+1)));
        }
        
        private static String IpPortOf(String ipport)
        {
            int pos = ipport.IndexOf("://");
            if (pos != -1)
                ipport = ipport.Substring(pos+3);
            pos = ipport.IndexOf('@');
            if (pos != -1)
                ipport = ipport.Substring(pos+1);
            pos = ipport.IndexOf('/');
            if (pos != -1)
                ipport = ipport.Substring(0, pos);
            return ipport;
        }
        
        
        public static EndPoint Create(IPAddress address, int port)
        {
            return CreateIP(address, port);
        }
        
        public static EndPoint Create(String host, int port)
        {
            // IPv4: d.d.d.d
            // IPv6: x:x:x:x:x:x:x:x
            //       x:x:x:x:x:x:d.d.d.d
            //       0:0:0:0:0:0:0:1
            //       ::1
            //       ::d.d.d.d
            
            // e' un nome!
            if (host.IndexOf('.') == -1 && host.IndexOf(':') == -1)
                return new DnsEndPoint(host, port);
            
            IPAddress address;
            if (IPAddress.TryParse(host, out address))
                return new IPEndPoint(address, port);
            else
                return new DnsEndPoint(host, port);
        }
        
        public static IPEndPoint CreateIP(IPAddress address, int port)
        {
            return new IPEndPoint(address, port);
        }
        
        public static IPEndPoint ParseIP(String host, int port)
        {
            IPAddress address;
            
            if (!IPAddress.TryParse(host, out address))
            {
                IPHostEntry iphe = Dns.GetHostEntry(host);
                if (iphe.AddressList.Length >= 1)
                    address = iphe.AddressList[0];
                else
                    address = IPAddress.Parse(host);
            }
                
            return new IPEndPoint(address, port);
        }
        
        public static int InterfaceIndex(IPAddress address)
        {
            IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
            for(int index=0; index<addresses.Length; ++index)
            {
                if (address.Equals(addresses[index]))
                    return index;
            }
            return -1;
        }
    }
}
